Разгледайте стрийминга на отговори от React Server Actions за прогресивни отговори на формуляри. Научете как да създавате по-бързи и отзивчиви формуляри за по-добро потребителско изживяване.
Стрийминг на отговори от React Server Actions: Прогресивен отговор на формуляри за подобрено потребителско изживяване
React Server Actions въвеждат мощна промяна на парадигмата в начина, по който обработваме операции от страна на сървъра в нашите React приложения. Една от най-вълнуващите функции е възможността за прогресивно стриймване на отговори, което ни позволява да предоставим незабавна обратна връзка на потребителите, дори преди цялата операция да приключи. Това е особено полезно за формуляри, където можем да създадем по-отзивчиво и ангажиращо потребителско изживяване, като актуализираме потребителския интерфейс, когато данните станат достъпни.
Разбиране на React Server Actions
Server Actions са асинхронни функции, които се изпълняват на сървъра, инициирани от React компоненти. Те предлагат няколко предимства пред традиционните API извиквания:
- Подобрена сигурност: Server Actions се изпълняват директно на сървъра, намалявайки риска от излагане на чувствителни данни или логика на клиента.
- Намален повтарящ се код: Те елиминират нуждата от отделни API пътища и логика за извличане на данни от страна на клиента.
- Подобрена производителност: Те могат да използват рендиране от страна на сървъра (SSR) и кеширане за по-бързо първоначално зареждане и подобрена производителност.
- Типова безопасност: С TypeScript, Server Actions осигуряват типова безопасност от край до край, гарантирайки консистентност на данните между клиента и сървъра.
Силата на стрийминга на отговори
Традиционното изпращане на формуляри често включва изпращане на всички данни към сървъра, изчакване на отговор и след това актуализиране на потребителския интерфейс. Това може да доведе до усещане за забавяне, особено при сложни формуляри или бавни мрежови връзки. Стриймингът на отговори позволява на сървъра да изпраща данни обратно към клиента на части, което ни дава възможност да актуализираме потребителския интерфейс прогресивно, когато данните станат достъпни.
Представете си формуляр, който изчислява сложна цена въз основа на въведените от потребителя данни. Вместо да чака цялото изчисление да приключи, сървърът може да стриймва междинни резултати обратно към клиента, предоставяйки обратна връзка в реално време на потребителя. Това може значително да подобри потребителското изживяване и да направи приложението да се усеща по-отзивчиво.
Имплементиране на прогресивен отговор на формуляр със Server Actions
Нека разгледаме пример за това как да имплементираме прогресивен отговор на формуляр с React Server Actions.
Пример: Конвертор на валути в реално време
Ще създадем прост формуляр за конвертиране на валута, който предоставя актуализации на обменния курс в реално време, докато потребителят въвежда сумата.
1. Настройка на Server Action
Първо, дефинираме Server Action, който обработва конвертирането на валута.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// Симулираме извличане на обменен курс от външен API
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Симулираме забавяне на мрежата
if (fromCurrency === 'USD' && toCurrency === 'EUR') return 0.92;
if (fromCurrency === 'EUR' && toCurrency === 'USD') return 1.09;
if (fromCurrency === 'USD' && toCurrency === 'JPY') return 145;
if (fromCurrency === 'JPY' && toCurrency === 'USD') return 0.0069;
throw new Error(`Exchange rate not found for ${fromCurrency} to ${toCurrency}`);
}
export const convertCurrency = async (prevState: any, formData: FormData) => {
const fromCurrency = formData.get('fromCurrency') as string;
const toCurrency = formData.get('toCurrency') as string;
const amount = Number(formData.get('amount'));
try {
if (!fromCurrency || !toCurrency || isNaN(amount)) {
return { message: 'Please provide valid input.' };
}
// Симулираме стрийминг на отговора
await new Promise(resolve => setTimeout(resolve, 250));
const exchangeRate = await unstable_cache(
async () => getExchangeRate(fromCurrency, toCurrency),
[`exchange-rate-${fromCurrency}-${toCurrency}`],
{ tags: [`exchange-rate-${fromCurrency}-${toCurrency}`] }
)();
await new Promise(resolve => setTimeout(resolve, 250));
const convertedAmount = amount * exchangeRate;
return { message: `Converted amount: ${convertedAmount.toFixed(2)} ${toCurrency}` };
} catch (e: any) {
console.error(e);
return { message: 'Failed to convert currency.' };
}
};
В този пример Server Action функцията convertCurrency
извлича обменния курс (симулирано със закъснение) и изчислява конвертираната сума. Добавили сме изкуствени закъснения с помощта на setTimeout
, за да симулираме мрежова латентност и да демонстрираме ефекта на стрийминг.
2. Имплементиране на React компонента
След това създаваме React компонента, който използва Server Action.
// app/page.tsx
'use client';
import { useState, useTransition } from 'react';
import { convertCurrency } from './server/actions';
import { useFormState } from 'react-dom';
export default function CurrencyConverter() {
const [fromCurrency, setFromCurrency] = useState('USD');
const [toCurrency, setToCurrency] = useState('EUR');
const [amount, setAmount] = useState('');
const [isPending, startTransition] = useTransition();
const [state, formAction] = useFormState(convertCurrency, { message: '' });
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
startTransition(() => {
formAction(new FormData(event.target as HTMLFormElement));
});
};
return (
<div>
<h2>Конвертор на валути в реално време</h2>
<form action={handleSubmit}>
<label htmlFor="fromCurrency">От:</label>
<select id="fromCurrency" name="fromCurrency" value={fromCurrency} onChange={(e) => setFromCurrency(e.target.value)}>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="toCurrency">Към:</label>
<select id="toCurrency" name="toCurrency" value={toCurrency} onChange={(e) => setToCurrency(e.target.value)}>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="amount">Сума:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? 'Конвертиране...' : 'Конвертирай'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
Ключови моменти:
- Използваме
useFormState
hook за управление на състоянието на формуляра и извикване на Server Action. - Състоянието
isPending
отuseTransition
деактивира бутона за изпращане и показва съобщение "Конвертиране...", докато действието се изпълнява, предоставяйки обратна връзка на потребителя. - Функцията
formAction
, върната отuseFormState
, автоматично обработва изпращането на формуляра и актуализира състоянието с отговора от Server Action.
3. Разбиране на прогресивните актуализации
Когато потребителят изпрати формуляра, се извиква функцията handleSubmit
. Тя създава обект FormData
от формуляра и го предава на функцията formAction
. След това Server Action се изпълнява на сървъра. Поради изкуствените закъснения, въведени в Server Action, ще наблюдавате следното:
- Бутонът за изпращане се променя на "Конвертиране..." почти веднага.
- След кратко забавяне (250ms), кодът симулира получаване на обменния курс.
- Конвертираната сума се изчислява и резултатът се изпраща обратно към клиента.
state.message
в React компонента се актуализира, показвайки конвертираната сума.
Това демонстрира как стриймингът на отговори ни позволява да предоставяме междинни актуализации на потребителя, когато данните станат достъпни, което води до по-отзивчиво и ангажиращо потребителско изживяване.
Предимства на прогресивния отговор на формуляри
- Подобрено потребителско изживяване: Предоставя незабавна обратна връзка на потребителите, което прави приложението да се усеща по-отзивчиво и по-малко мудно.
- Намалено усещане за забавяне: Като се показват междинни резултати, потребителите възприемат процеса като по-бърз, дори ако цялата операция отнема същото време.
- Повишена ангажираност: Поддържа потребителите ангажирани, като предоставя актуализации в реално време и ги предпазва от изоставяне на формуляра поради усещане за забавяне.
- Увеличени проценти на конверсия: По-гладкото и отзивчиво потребителско изживяване може да доведе до по-високи проценти на конверсия, особено при сложни формуляри.
Напреднали техники
1. Използване на `useOptimistic` за незабавни актуализации на потребителския интерфейс
Хукът useOptimistic
ви позволява оптимистично да актуализирате потребителския интерфейс, преди Server Action да е приключил. Това може да осигури още по-бързо усещане за реакция, тъй като потребителският интерфейс отразява очаквания резултат незабавно.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// Връщане на новото състояние въз основа на актуализацията
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: 'optimistic update' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>Актуализирай</button>
</div>
);
}
В примера с конвертора на валута можете оптимистично да актуализирате конвертираната сума въз основа на текущия обменен курс, предоставяйки незабавен преглед на потребителя, преди действителното изчисление да приключи на сървъра. Ако сървърът върне грешка, можете да върнете оптимистичната актуализация.
2. Имплементиране на обработка на грешки и резервни механизми
От решаващо значение е да се имплементират стабилни механизми за обработка на грешки и резервни варианти за справяне със случаи, когато Server Action се провали или мрежовата връзка е прекъсната. Можете да използвате блока try...catch
в рамките на Server Action, за да улавяте грешки и да връщате подходящо съобщение за грешка на клиента.
// server/actions.ts
export const convertCurrency = async (prevState: any, formData: FormData) => {
// ...
try {
// ...
} catch (error: any) {
console.error(error);
return { message: 'Възникна грешка при конвертиране на валутата. Моля, опитайте отново по-късно.' };
}
};
От страна на клиента можете да покажете съобщението за грешка на потребителя и да предоставите опции за повторен опит на операцията или за връзка с поддръжката.
3. Кеширане на обменни курсове за по-добра производителност
Извличането на обменни курсове от външен API може да бъде пречка за производителността. За да подобрите производителността, можете да кеширате обменните курсове, като използвате кеширащ механизъм като Redis или Memcached. Функцията unstable_cache
от Next.js (както е използвана в примера) предоставя вградено решение за кеширане. Не забравяйте периодично да инвалидирате кеша, за да се уверите, че обменните курсове са актуални.
4. Съображения за интернационализация
Когато създавате приложения за глобална аудитория, е важно да се вземе предвид интернационализацията (i18n). Това включва:
- Форматиране на числа: Използвайте подходящи формати на числа за различните локали (напр. използване на запетаи или точки като десетични разделители).
- Форматиране на валута: Показвайте валутни символи и формати според локала на потребителя.
- Форматиране на дата и час: Използвайте подходящи формати за дата и час за различните локали.
- Локализация: Преведете потребителския интерфейс на различни езици.
Библиотеки като Intl
и react-intl
могат да ви помогнат да имплементирате i18n във вашите React приложения.
Примери от реалния свят и случаи на употреба
- Електронна търговия: Показване на разходите за доставка и прогнозите за доставка в реално време, докато потребителят добавя артикули в количката си.
- Финансови приложения: Предоставяне на котировки на акции и актуализации на портфолио в реално време.
- Резервации за пътувания: Показване на цени и наличност на полети в реално време.
- Визуализация на данни: Стрийминг на актуализации на данни към диаграми и графики.
- Инструменти за сътрудничество: Показване на актуализации на документи и проекти в реално време.
Заключение
Стриймингът на отговори от React Server Action предлага мощен начин за подобряване на потребителското изживяване на вашите React приложения. Като предоставяте прогресивни отговори на формуляри, можете да създавате по-бързи, по-отзивчиви и по-ангажиращи формуляри, които задържат потребителите ангажирани и подобряват процентите на конверсия. Чрез комбиниране на стрийминг на отговори с техники като оптимистични актуализации и кеширане, можете да изградите наистина изключителни потребителски изживявания.
С продължаващото развитие на React Server Actions можем да очакваме появата на още по-мощни функции и възможности, които допълнително ще опростят разработката на сложни и динамични уеб приложения.
За допълнително проучване
Това ръководство предоставя изчерпателен преглед на стрийминга на отговори от React Server Action и неговото приложение за прогресивни отговори на формуляри. Като разберете концепциите и техниките, обсъдени тук, можете да използвате тази мощна функция, за да създавате по-бързи, по-отзивчиви и по-ангажиращи уеб приложения.